package JVM.第06篇_垃圾回收篇;

/**
 *
 * 并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。
 *  无论从微观还是从宏观来看，二者都是一起执行的。
 * 并发:一个CPU (采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事|
 * 宏观上具有多个进程同时执行的效果，但在微观上并不是同时执行的
 * 4种垃圾回收器
 */
/**
 *     1.Serial（串行） -XX:+UseSerialGC
 *         它为单线程环境设计且只使用一个线程进行垃圾回收，会暂停所有的用户线程。
 *         所以不适合服务器环境,是用的复制算法
 *         优势:简单而高效(与其他收集器的单线程比)，
 *              对于限定单个CPU的环境来说，Serial收集器由于没有线程交互的开销，
 *              专心做垃圾收集自然可以获得最高的单线程收集效率。
 *            运行在Client模式下的虚拟机是个不错的选择。
 *           在用户的桌面应用场景中，可用内存一般不大(几十MB至一两百MB)，
 *           可以在较短时间内完成垃圾收集(几十ms至一百多ms) ,
 *           只要不频繁发生，使用串行回收器是可以接受的。
 */
/**     2.Parallel（并行） -XX:+UseParallelGC  //JDK8默认
 *         多个垃圾收集线程并行工作，此时用户线程是暂停的，
 *         适用于 科学计算/大数据处理 首台处理等弱交互场景
 *         ● 和ParNew收集器不同，Parallel Scavenge收集器的目标则是达到一个可控制
 *          的吞吐量(Throughput)，它也被称为吞吐量优先的垃圾收集器。
 *         ●自适应调节策略也是Parallel Scavenge 与ParNew一个重要区别。
 *         如，调整老年代比例为8  则 比例为 8:1:1  但是自适应会改成6:1:1
 *      参数配置:
 *          ●-XX:+UseParallelGC 手动指定年轻代使用Parallel并行收集器执行内存回收任务
 *          ●-XX:+UseParallelOldGC 手动指定老年代都是使用并行回收收集器。
 *              ●分别适用于新生代和老年代。默认jdk8是开启的。
 *              ●上面两个参数，默认开启一个，另一个也会被开启。(互相激活)
 *          ●-XX:ParallelGCThreads设置年轻代并行收集器的线程数。
 *          一般地，最好与CPU数量相等，以避免过多的线程数影响垃圾收集性能。
 *              ●在默认情况下，当CPU 数量小于8个，ParallelGCThreads 的值等于CPU数量。
 *              ●当CPU数量大于8个，ParallelGCThreads 的值等于3+[5*CPU_Count]/8]。
 *          ●-XX:MaxGCPauseMillis 设置垃圾收集器最大停顿时间(即STW的时间)。 单位是亳秒
 *              ●为了尽可能地把停顿时间控制在MaxGCPauseMills以内，收集器在工作时会调整
 *              Java堆大小或者其他一些参数。
 *              ●对于用户来讲，停顿时间越短体验越好。但是在服务器端，我们注重高并发，
 *              整体的吞吐量。所以服务器端适合Parallel,进行控制。
 *              ●该参数使用需谨慎。
 *          ●-XX:GCTimeRatio 垃圾收集时间占总时间的比例(= 1 / (N + 1))。
 *          用于衡量吞吐量的大小。
 *              ●取值范围(0,100)。默认值99，也就是垃圾回收时间不超过1%。
 *              ●与前一个-XX:MaxGCPauseMillis参数有一定矛盾性。
 *              暂停时间越长，Radio参数就容易超过设定的比例。
 *          ●-XX: +UseAdaptiveSizePolicy设置Parallel Scavenge收集器具有白适应调节策略
 *              ●在这种模式下，年轻代的大小、Eden和Survivor的比例、晋升老年代的对象年龄等参数会被自动调整，
 *              已达到在堆大小、吞吐量和停顿时间之间的平衡点。
 *              ●在手动调优比较困难的场合，可以直接使用这种自适应的方式，仅指定虚拟机的
 *              最大堆、目标的吞吐量( GCTimeRatio)和停顿时间(MaxGCPauseMills)
 *              让虚拟机自己完成调优工作。
 */
/**     3.CMS（并发）//用户线程和垃圾收集线程同时执行(不一定是并行，可能交替执行)，不需要停顿用户线程
 *                 //互联网公司多用它，适用对响应时间有要求的场景
 *         -XX:+UseConcMarkSweepGC
 *         1.初始标记(CMS initial mark) //记录GC Roots位置  暂时时间非常短，标记与GC Roots直接关联的对象。
 *         2.并发标记(CMS concurrent mark)和用户线程一起 (最耗时) 从GC Roots开始遍历整个对象图的过程。不会停顿用户线程
 *         3.重新标记(CMS remark)// 二次确认 会停顿
 *         4.并发清除(CMS concurrent sweep)和用户线程一起
 *         优点:并发收集底停顿
 *         缺点:对CPU的资源压力大，标记清除有大量碎片
 *         -XX:CMSFullGCsBeForeCompaction(默认0， 即每次都进行内存整理（标记压缩）)
 *
 *  内存使用到一定比例就会执行
 *   由于并发进行，CMS在收集与应用线程会同时会增加对堆内存的占用，也就是说，CMS必须要在老年代堆内存用尽之前完成垃圾回收，
 *   否则CMS回收失败时，将触发担保机制，串行老年代收集器将会以STW的方式进行一次GC，从而造成较大停顿时间
 *
 *   CMS收集器(Concurrent Mark Sweep:并发标记清除)
 *   是一种以获取最短回收停顿时间为目标的收集器。
 *   适合应用在互联网站或者B/S系统的服务器上，这类应用尤其重视服务器的响应速度，希望系统停顿时间最短。
 *   CMS非常适合堆内存大、CPU核数多的服务器端应用，也是G1出现之前大型应用的首选收集器。
 *
 * CMS的优点:
 *      ●并发收集
 *      ●低延迟
 * CMS的弊端:
 *      1)会产生内存碎片，导致并发清除后，用户线程可用的空间不足。
 *      在无法分配大对象的情况下，不得不提前触发Full GC。
 *      2) CMS收集器对CPU资源非常敏感。在并发阶段，它虽然不会导致用户停顿，
 *      但是会因为占用了一部分线程而导致应用程序变慢，总吞吐量会降低。
 *      3) CMS收集器无法处理浮动垃圾。可能出现“Concurrent Mode Failure” 失败而导致
 *      另一次FullGC的产生。在并发标记阶段由于程序的工作线程和垃圾收集线程是同时运
 *      行或者交叉运行的，那么在并发标记阶段如果产生新的垃圾对象，CMS将无法对这些垃圾
 *      对象进行标记，最终会导致这些新产生的垃圾对象没有被及时回收，从而只能在下一次执
 *      行GC时释放这些之前未被回收的内存空间。
 *
 * ●-XX:+UseConcMarkSweepGC 手动指定使用CMS收集器执行内存回收任务。
 *      ●开启该参数后会自动将-XX:+UseParNewGC打开。
 *      即: ParNew(Young区用)+CMS(01d区用)+Serial 01d的组合。
 * ●-Xx:CMSlnitiatingoccupanyFraction 设置堆内存使用率的阈值，一 旦达到该阈
 * 值，便开始进行回收。
 *      ●JDK5及以前版本的默认值为68，即当老年代的空间使用率达到68%时，会执行一-
 *      次CMS回收。JDK6及以上版本默认值为92%
 *      ●如果内存增长缓慢，则可以设置一个稍大的值，大的阈值可以有效降低CMS的触
 *      发频率，减少老年代回收的次数可以较为明显地改善应用程序性能。反之，如果
 *      应用程序内存使用率增长很快，则应该降低这个阈值，以避免频繁触发老年代串
 *      行收集器。因此通过该选项便可以有效降低Full GC的执行次数。
 * - XX: +UseCMSCompactAtFullCollection用于指定在执行完Fu1l GC后对内存空间
 * 进行压缩整理，以此避免内存碎片的产生。不过由于内存压缩整理过程无法并发执行，
 * 所带来的问题就是停顿时间变得更长了。
 * - XX:CMSFullGCsBeforeCompaction设置在执行多少次Fu1l GC后对内存空间进行
 * 压缩整理。
 *
 */
/**     4.G1//将堆内存分割成不同区域  分别进行CMS（并发）
 *       XX:+UseG1GC
 *   G1:   //已经不分新生代和老年代
 *      是一种面向服务端的垃圾收集器
 *      应对多处理器和大容量的内存       在实现高吞吐量的同时 尽可能的满足垃圾收集暂停时间的要球
 *      目的是取代CMS收集器
 *          G1是一个由整理内存过程的垃圾收集器不会产生很多内存碎片
 *          G1的Stop The  World(STW)更可控，G1在停顿时间上添加了预测机制，用户可以指定期望停顿时间。
 *
 * 与其他GC收集器相比。G1使用了全新的分区算法，其特点如下所示:
 *    并行与并发
 *         ●并行性: G1 在回收期间，可以有多个GC线程同时工作，有效利用多核计算能力。
 *         此时用户线程STW
 *         ●并发性: G1拥有与应用程序交替执行的能力，部分工作可以和应用程序同时执行
 *         因此，一般来说，不会在整个回收阶段发生完全阻塞应用程序的情况
 *    分代收集
 *         ●从分代上看，G1依然属于分代型垃圾回收器，它会区分年轻代和老年代，
 *         年轻代依然有Eden区和Survivor区。
 *         但从堆的结构上看，它不要求整个Eden区、年轻代或者老年代都是连续的，也不再坚持固定大小和固定数量。
 *         ●将堆空间分为若干个区域(Region)， 这些区域中包含了逻辑上的年轻代和老年代。
 *         ●和之前的各类回收器不同，它同时兼顾年轻代和老年代。
 *         对比其他回收器，或者工作在年轻代，或者工作在老年代;
 *
 *      1: G1能充分利用多CPU、多核环境硬件优势，尽量缩短STW。
 *      2: G1整体正采用标记-整理算法，局部是通过复制算法，不会产生内存碎片。
 *      3: 宏观上看G1之中不再区分年轻代和老年代。把内存划分成多个独立的 子区域(Region),
 *          可以近似理解为一个围棋的棋盘。
 *      4: G1收集器里面讲整个的内存区都混合在一起了，但其本身依然在小范围内要进行年轻代和老年代的区分，
 *          保留了新生代和老年代，但它们不再是物理隔离的，而是一部分Region的集合且不需要Region是连续的，
 *          也就是说依然会采用不同的GC方式来处理不同的区域。
 *      5: G1虽然也是分代收集器，但整个内存分区不存在物理上的年轻代与老年代的区别，
 *         也不需要完全独立的survivor(to space)堆做复制准备。
 *         G1只有逻辑上的分代概念，或者说每个分区都可能随G1的运行在不同代之间前后切换;
 *
 *      -XX:G1HeapRegionSize=n可指定分区大小（1-32  MB）  但必须是2的幂
 *
 *      Region区域化垃圾收集器
 *      Eden     Survivor   Old    Humongous
 *      伊甸园区   幸存区     养老区   巨大的(大对象)
 *
 *
 *      区域化内存划片Region，整体编为了一些列不连续的内存区域，避免了全内存区的GC操作。
 *      核心思想是将整个堆内存区域分成大小相同的子区域(Region),在JVM启动时会自动设置这些子区域的大小，
 *      在堆的使用上，G1并不要求对象的存储一定是物理上连续的只要逻辑上连续即可，
 *      每个分区也不会固定地为某个代服务，可以按需在年轻代和老年代之间切换。
 *      启动时可以通过参数XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB，且必 须是2的幂)，
 *      默认将整堆划分为2048个分区。
 *      大小范围在1MB~32MB，最多能设置2048个区域，
 *          也即能够支持的最大内存为: 32MB * 2048 = 65536MB = 64G内存
 *
 *          在G1中，还有一种特殊的区域，叫Humongous(巨大的)区域
 *      如果一个对象占用的空间超过了分区容量50%以上，G1收集器就认为这是一个巨型对象。
 *      这些巨型对象默认直接会被分配在年老代
 *      但是如果它是一个短期存在的巨型对象，就会对垃圾收集器造成负面影响。
 *      为了解决这个问题，G1划分了一个Humongous区，它用来专门存放巨型对象。
 *      如果一个H区装不下一个巨型对象，那么G1会寻找连续的H分区来存储。
 *      为了能找到连续的H区，有时候不得不启动Full GC。
 *
 *
 *   G1:四部
 *         1.初始标记:只标记  GC Roots能 直接关联到的对象
 *         2.并发标记:进行    GC Roots Tracing的过程
 *         3.最终标记:修正并发标记期间，因程序运行导致标记发生变化的那一部分对象
 *         4.筛选回收:根据时间来进行价值最大化的回收
 *
 * -XX:+UseG1GC
 * -XX:G1HeapRegionSize=n:设置的G1区域的大小。值是2的幂，范围是1MB到32MB。目标是根据最小的Java堆大
 * -XX:MaxGCPauseMillis=n:最大GC停顿时间，这是i个软目标，JVM将尽可能(但不保证)停顿小于这个时间
 * -XX:InitiatingHeapOccupancyPercent=n:堆占用了多少的时候就触发GC，默认为45
 * -XX:ConcGCThreads=n: 并发Gc使用的线程数
 * -XX:G1ReservePercent=n:设置作为空闲空间的预留内存百分比，以降低目标空间溢出的风险，默认值是10%
 *
 *
 */
/**     5.ZGC(0..jdk11及以后）
 *  令人震惊、革命性的ZGC
 *   ZGC与Shenandoah目标高度相似，在尽可能对吞吐量影响不大的前提下，
 *   实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在十亳秒以内的低延迟。
 *   ZGC:是一款基于Region内存布成的，(暂时) 不设分代的，使用了读屏障、染色指针和
 *   内存多重映射等技术来实现可并发的标记-压缩算法的，以低延迟为首要目标的一款垃圾收集器。
 *   ZGC的工作过程可以分为4个阶段:并发标记-并发预备重分配-并发重分配-并发重映射等
 *   ZGC几乎在所有地方并发执行的，除了初始标记的是STW的。所以停顿时间几乎就耗费在初
 *   始标记上，这部分的实际时问是非常少的。
 *
 */

public class J4_垃圾回收器 {

}
